{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "bottom-directional-drawer", "type": "registry:component", "dependencies": [ "motion", "lucide-react" ], "devDependencies": [], "registryDependencies": [], "files": [ { "path": "./components/ui/directional-drawer.tsx", "content": "'use client';\r\nimport React, {\r\n createContext,\r\n useContext,\r\n useState,\r\n useEffect,\r\n ReactNode,\r\n} from 'react';\r\nimport { X } from 'lucide-react';\r\nimport { Drawer as VaulSidebar } from 'vaul';\r\nimport { cn } from '@/lib/utils';\r\n\r\ninterface DrawerContextProps {\r\n open: boolean;\r\n setOpen: (open: boolean) => void;\r\n}\r\n\r\nconst DrawerContext = createContext(undefined);\r\n\r\nexport const useDirectionalDrawer = () => {\r\n const context = useContext(DrawerContext);\r\n if (!context) {\r\n throw new Error('useDirectionalDrawer must be used within a DirectionalDrawer');\r\n }\r\n return context;\r\n};\r\n\r\ninterface DirectionalDrawerProps {\r\n children: ReactNode;\r\n open?: boolean;\r\n setOpen?: (open: boolean) => void;\r\n direction?: 'left' | 'right' | 'top' | 'bottom';\r\n outsideClose?: boolean;\r\n className?: string;\r\n}\r\n\r\nexport function DirectionalDrawer({\r\n children,\r\n open: controlledOpen,\r\n setOpen: controlledSetOpen,\r\n direction = 'left',\r\n outsideClose = true,\r\n className,\r\n}: DirectionalDrawerProps) {\r\n const [internalOpen, setInternalOpen] = useState(false);\r\n const [isDesktop, setIsDesktop] = useState(false);\r\n\r\n const open = controlledOpen !== undefined ? controlledOpen : internalOpen;\r\n const setOpen = controlledSetOpen || setInternalOpen;\r\n\r\n useEffect(() => {\r\n const mediaQuery = window.matchMedia('(min-width: 768px)');\r\n const handleMediaChange = (event: MediaQueryListEvent) => {\r\n setIsDesktop(event.matches);\r\n };\r\n\r\n setIsDesktop(mediaQuery.matches);\r\n mediaQuery.addEventListener('change', handleMediaChange);\r\n\r\n return () => {\r\n mediaQuery.removeEventListener('change', handleMediaChange);\r\n };\r\n }, []);\r\n\r\n const trigger = React.Children.toArray(children).find(\r\n (child: any) => child.type === DrawerTrigger\r\n );\r\n const content = React.Children.toArray(children).filter(\r\n (child: any) => child.type !== DrawerTrigger\r\n );\r\n\r\n // Helper function to get positioning and sizing classes\r\n const getDirectionClasses = () => {\r\n switch (direction) {\r\n case 'right':\r\n return {\r\n position: 'right-0 bottom-0',\r\n size: outsideClose \r\n ? 'sm:w-[450px] w-[90%] h-full' \r\n : 'w-full h-full',\r\n border: 'border-l',\r\n handlePosition: 'top-[40%] left-2',\r\n handleSize: 'h-16 w-[0.30rem]'\r\n };\r\n case 'top':\r\n return {\r\n position: 'top-0 left-0',\r\n size: outsideClose \r\n ? 'w-full sm:h-[450px] h-[90%]' \r\n : 'w-full h-full',\r\n border: 'border-b',\r\n handlePosition: 'bottom-2 left-[40%]',\r\n handleSize: 'w-16 h-[0.30rem]'\r\n };\r\n case 'bottom':\r\n return {\r\n position: 'bottom-0 left-0',\r\n size: outsideClose \r\n ? 'w-full sm:h-[450px] h-[90%]' \r\n : 'w-full h-full',\r\n border: 'border-t',\r\n handlePosition: 'top-2 left-[40%]',\r\n handleSize: 'w-16 h-[0.30rem]'\r\n };\r\n case 'left':\r\n default:\r\n return {\r\n position: 'left-0 bottom-0',\r\n size: outsideClose \r\n ? 'sm:w-[450px] w-[90%] h-full' \r\n : 'w-full h-full',\r\n border: 'border-r',\r\n handlePosition: 'top-[40%] right-2',\r\n handleSize: 'h-16 w-[0.30rem]'\r\n };\r\n }\r\n };\r\n\r\n const directionClasses = getDirectionClasses();\r\n const vaulDirection = direction === 'right' ? 'right' : \r\n direction === 'top' ? 'top' : \r\n direction === 'bottom' ? 'bottom' : 'left';\r\n\r\n return (\r\n \r\n {trigger}\r\n\r\n \r\n \r\n setOpen(false)}\r\n />\r\n \r\n \r\n {isDesktop ? (\r\n setOpen(false)}\r\n >\r\n \r\n \r\n ) : (\r\n \r\n )}\r\n {content}\r\n \r\n \r\n \r\n \r\n \r\n );\r\n}\r\n\r\nexport function DrawerContent({\r\n children,\r\n className,\r\n}: {\r\n children: ReactNode;\r\n className?: string;\r\n}) {\r\n return
{children}
;\r\n}\r\n\r\nexport function DrawerTrigger({ children }: { children: ReactNode }) {\r\n const { setOpen } = useDirectionalDrawer();\r\n return
setOpen(true)}>{children}
;\r\n}", "type": "registry:component" }, { "path": "./registry/components/drawer/bottom-directional-drawer.tsx", "content": "'use client';\r\nimport { Drawer } from 'vaul';\r\nimport { motion } from 'motion/react';\r\nimport { useState } from 'react';\r\nimport { Edit, X } from 'lucide-react';\r\nimport { useMediaQuery } from '@/hooks/use-media-query';\r\nimport Image from 'next/image';\r\nimport {\r\n DirectionalDrawer,\r\n DrawerContent,\r\n DrawerTrigger,\r\n} from '@/components/ui/directional-drawer';\r\nexport default function index() {\r\n const [sidebarOpen, setSidebarOpen] = useState(false);\r\n return (\r\n <>\r\n \r\n \r\n
\r\n

Update Profile Image

\r\n

\r\n Upload a new profile image or remove the current one.\r\n

\r\n
\r\n \r\n \r\n JP\r\n \r\n \r\n
\r\n \r\n
\r\n \r\n Submit\r\n \r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n setSidebarOpen(true)}\r\n className='absolute left-2 bottom-2 p-4 dark:bg-black bg-white rounded-lg shadow-black'\r\n >\r\n \r\n \r\n
\r\n
\r\n \r\n );\r\n}\r\n", "type": "registry:component" } ] }